////////////////////////////////////////////////////////////////////////////////

#ifndef _BUFFER_H_
#define _BUFFER_H_

////////////////////////////////////////////////////////////////////////////////

#include <cstring>

////////////////////////////////////////////////////////////////////////////////



/** Memory storage for any types
*   
*  @author   Roman Pasechnik
*  @since    Jul 09th, 2009
*  @updated  Jul 26th, 2009
*/
class Buffer
{
////////////////////////////////////////////////////////////////////////////////

public:

////////////////////////////////////////////////////////////////////////////////


    /** Default Constructor */
    Buffer();


    /** Constructor from memory */
    Buffer( const char* _str, size_t _numElems );


    /** Copy constructor */
    Buffer( const Buffer& _rhs );


    /** Assignment operator */
    const Buffer& operator=( const Buffer& _rhs );


////////////////////////////////////////////////////////////////////////////////


    /** Get pointer to data */
    const char* Data() const;


    /** Get pointer to data (non-const version) */
    char* Data();


    /** Get buffer size */
    size_t Size() const;


    /** Set buffer size */
    void SetSize( size_t _size );


    /** Clear buffer */
    void Clear();


////////////////////////////////////////////////////////////////////////////////


    /** Internal buffer size */
    enum { MAX_BUFFER_SIZE = 1024 };


////////////////////////////////////////////////////////////////////////////////


    /** Huffman encode */
    void Encode();


    /** Huffman decode */
    void Decode();


////////////////////////////////////////////////////////////////////////////////


    /** Equality operator */
    bool operator==( const Buffer& _rhs ) const;


    /** Inequality operator */
    bool operator!=( const Buffer& _rhs ) const;


////////////////////////////////////////////////////////////////////////////////
// Stream input and output
////////////////////////////////////////////////////////////////////////////////
    

    /** Output to buffer */
    template <typename T>
    friend Buffer& operator<<(Buffer& _buffer, const T& _value );


    /** Input from buffer */
    template <typename T>
    friend Buffer& operator>>(Buffer& _buffer, T& _value );


////////////////////////////////////////////////////////////////////////////////

private:

////////////////////////////////////////////////////////////////////////////////


    /** Assign string to buffer */
    void Assign( const char* _str, size_t _size );


////////////////////////////////////////////////////////////////////////////////


    /** Buffer data */
    char m_Data[MAX_BUFFER_SIZE];


    /* Begin of the buffer */
    size_t m_BeginIdx;


    /* End of the buffer */
    size_t m_EndIdx;


////////////////////////////////////////////////////////////////////////////////
};



/** Template realizations */

template <typename T>
Buffer& operator<<( Buffer& _buffer, const T& _value )
{
    memcpy( _buffer.m_Data + _buffer.m_EndIdx, &_value, sizeof(T) );
    _buffer.m_EndIdx += sizeof(T);
    return _buffer;
}


////////////////////////////////////////////////////////////////////////////////


template <typename T>
Buffer& operator>>( Buffer& _buffer, T& _value )
{
    memcpy( &_value, _buffer.m_Data + _buffer.m_BeginIdx, sizeof(T) );
    _buffer.m_BeginIdx += sizeof(T);
    return _buffer;
}


////////////////////////////////////////////////////////////////////////////////

#endif

////////////////////////////////////////////////////////////////////////////////
